﻿using System.Data.Entity;
using XStudio.XCRF.Data.Entities.BasicInfo;
using XStudio.XCRF.Data.Entities.LabCheck;
using XStudio.XCRF.Data.Entities;
using XStudio.XCRF.Data.Entities.CureInfo;
using System.Data.Entity.Validation;
using System.Data.Entity.Infrastructure;
using System.Collections.Generic;
using System.Data;
using System;
using System.Linq;
using XStudio.XCRF.Data.Business;
using XStudio.XCRF.Data.Business.Validate;
using XStudio.XCRF.Data.Business.Archieve;
using XStudio.XCRF.Data.Entities.TongueAndPulse;

namespace XStudio.XCRF.Data
{
    /// <summary>
    /// XCRF数据库访问上下文对象
    /// </summary>
    public class XCRFContext : DbContext
    {
        #region 核心

        /// <summary>
        /// 构造函数，创建新的数据库连接
        /// </summary>
        /// <param name="con">XCRF数据库链接</param>
        public XCRFContext(XCRFConnection con)
            : base(con.DbConnection, true)
        {
            //Configuration.LazyLoadingEnabled = true;
        }
        /// <summary>
        /// 构造函数，使用默认XCRF数据库连接
        /// </summary>
        public XCRFContext()
            : this(new XCRFConnection())
        {
            
        }

        private Member _CurrentMember;
        /// <summary>
        /// 获取和设置当前用户的信息
        /// </summary>
        public Member CurrentMember
        {
            get { return GetCurrentMember(); }
            set { SetCurrentMember(value); }
        }

        /// <summary>
        /// 获取当前业务逻辑是否为匿名用户
        /// </summary>
        public bool IsAnonymous { get { return _CurrentMember == null; } }

        /// <summary>
        /// 获取当前用户
        /// </summary>
        /// <returns></returns>
        public Member GetCurrentMember()
        {
            if (_CurrentMember == null)
                throw new Exception("尚未设置当前用户，处于匿名状态");
            return _CurrentMember;
        }

        /// <summary>
        /// 设置当前用户
        /// </summary>
        /// <param name="id">用户ID</param>
        public void SetCurrentMember(Guid id)
        {
            Member member = Members.Find(id);
            SetCurrentMember(member);
        }

        /// <summary>
        /// 设置当前用户
        /// </summary>
        /// <param name="member">用户</param>
        public void SetCurrentMember(Member member)
        {
            if (_CurrentMember == null)
            {
                _CurrentMember = null;
            }
            else
            {
                bool hasChanges = ChangeTracker.Entries<IArchieve>().Any(e =>
                    e.State == EntityState.Added ||
                    e.State == EntityState.Deleted ||
                    e.State == EntityState.Modified);
                if (hasChanges)
                    throw new Exception("挂起的更改尚未处理，不允许更改当前操作用户");
            }
            _CurrentMember = member;
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //一些补充映射规则，解决无法自动映射的问题
            
            //解决成员的历史记录跟踪问题 Member <--> Member系统将会混淆，必须手动指定
            modelBuilder.Entity<Member>().HasOptional(member => member.Creater).WithMany();
            modelBuilder.Entity<Member>().HasOptional(member => member.LastModifier).WithMany();

            //治疗信息 <--> 主证 多对多关系
            modelBuilder.Entity<CureInfo>().HasMany(cure => cure.PrimarySyms)
                .WithMany(disease => disease.PriCureInfoes)
                .Map(map => map.ToTable("CureInfoPrimarySyms"));
            //治疗信息 <--> 次证 多对多关系
            modelBuilder.Entity<CureInfo>().HasMany(cure => cure.SubSyms)
                .WithMany(disease => disease.SubCureInfoes)
                .Map(map => map.ToTable("CureInfoSubSyms"));
            base.OnModelCreating(modelBuilder);
        }

        /// <summary>
        /// 获取和设置是否启动调试模式
        /// </summary>
        internal bool DebugModeOn { get; set; }

        /// <summary>
        /// 重写保存更改方法
        /// </summary>
        /// <returns></returns>
        public override int SaveChanges()
        {
            if (DebugModeOn)
                return base.SaveChanges();
            DateTime time = DateTime.Now;
            IEnumerable<DbEntityEntry<IArchieve>> entries = ChangeTracker.Entries<IArchieve>();
            foreach (DbEntityEntry<IArchieve> entry in entries)
            {
                EntityState state = entry.State;
                if (state == EntityState.Unchanged || state == EntityState.Detached)
                    continue;
                IArchieve entity = entry.Entity;
                Guid memberID = CurrentMember.ID;
                switch (state)
                {
                    case EntityState.Deleted:
                        entry.State = EntityState.Modified;
                        entity.IsDeleted = true;
                        break;
                    case EntityState.Added:
                        entity.CreaterID = memberID;
                        entity.CreateTime = time;
                        break;
                    case EntityState.Modified:
                        IArchieve originalEntity = (IArchieve)entry.OriginalValues.ToObject();
                        IArchieve archieve = originalEntity.CreateArchieve();
                        Entry(archieve).State = EntityState.Added;
                        break;
                }
                entity.LastModifierID = memberID;
                entity.LastModifyTime = time;
            }
            return base.SaveChanges();
        }

        /// <summary>
        /// 重写验证实体方法
        /// </summary>
        /// <param name="entityEntry"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
        {
            if(DebugModeOn)
                return base.ValidateEntity(entityEntry, items);
            object entity = entityEntry.Entity;
            if(!typeof(IArchieve).IsInstanceOfType(entity))
                return base.ValidateEntity(entityEntry, items);
            if (((IArchieve)entity).IsDeleted)
                return base.ValidateEntity(entityEntry, items);
            object[] attrs = entity.GetType().GetCustomAttributes(typeof(ValidateAttribute), true);
            if (attrs.Length == 0)
                return base.ValidateEntity(entityEntry, items);
            ValidateAttribute vattr = (ValidateAttribute)attrs[0];
            IEnumerable<DbValidationError> errors = null;
            switch (entityEntry.State)
            {
                case EntityState.Added: errors = vattr.ValidateAdd(entityEntry, this); break;
                case EntityState.Modified: errors = vattr.ValidateEdit(entityEntry, this); break;
                case EntityState.Deleted: errors = vattr.ValidateDelete(entityEntry, this); break;
                default: return base.ValidateEntity(entityEntry, items);
            }
            if (errors.Any())
            {
                DbEntityValidationResult result = new DbEntityValidationResult(entityEntry, errors);
                return result;
            }
            return base.ValidateEntity(entityEntry, items);
        }

        #endregion 核心

        #region 实体集合
        /// <summary>
        /// 医院
        /// </summary>
        public DbSet<Hospital> Hospitals { get; set; }
        /// <summary>
        /// 系统成员
        /// </summary>
        public DbSet<Member> Members { get; set; }
        /// <summary>
        /// 患者信息
        /// </summary>
        public DbSet<Patient> Patients { get; set; }
        /// <summary>
        /// CRF记录
        /// </summary>
        public DbSet<CRF> CRFs { get; set; }
        /// <summary>
        /// 病例报告基本信息
        /// </summary>
        public DbSet<BasicInfo> BasicInfoes { get; set; }
        #region 基本信息
        /// <summary>
        /// 家族史
        /// </summary>
        public DbSet<FamilyHistory> FamilyHistories { get; set; }
        /// <summary>
        /// 过敏史
        /// </summary>
        public DbSet<AllergyHistory> AllergyHistories { get; set; }
        /// <summary>
        /// 基本信息 化疗信息
        /// </summary>
        public DbSet<BasicChemo> BasicChemoes { get; set; }
        /// <summary>
        /// 基本信息 放疗信息
        /// </summary>
        public DbSet<BasicRadio> BasicRadioes { get; set; }
        /// <summary>
        /// 基本信息 其他治疗信息
        /// </summary>
        public DbSet<BasicOtherCure> BasicOtherCures { get; set; }
        /// <summary>
        /// 基本信息 合并用药信息
        /// </summary>
        public DbSet<BasicOtherMerge> BasicOtherMerges { get; set; }
        #endregion 基本信息
        /// <summary>
        /// 实验室检查信息
        /// </summary>
        public DbSet<LabCheck> LabChecks { get; set; }
        /// <summary>
        /// 实验室检查标准信息
        /// </summary>
        public DbSet<LabCheckStd> LabCheckStds { get; set; }
        /// <summary>
        /// 治疗信息
        /// </summary>
        public DbSet<CureInfo> CureInfoes { get; set; }
        #region 治疗信息
        /// <summary>
        /// 中成药、中药注射液
        /// </summary>
        public DbSet<Inject> Injects { get; set; }
        /// <summary>
        /// 治疗信息 化疗信息
        /// </summary>
        public DbSet<CureChemo> CureChemoes { get; set; }
        /// <summary>
        /// 治疗信息 放疗信息
        /// </summary>
        public DbSet<CureRadio> CureRadioes { get; set; }
        /// <summary>
        /// 治疗信息 超声刀信息
        /// </summary>
        public DbSet<CureSound> CureSounds { get; set; }
        /// <summary>
        /// 治疗信息 伽马刀信息
        /// </summary>
        public DbSet<CureGamma> CureGammas { get; set; }
        /// <summary>
        /// 治疗信息 其他治疗信息
        /// </summary>
        public DbSet<CureOtherCure> CureOtherCures { get; set; }
        #endregion 治疗信息

        /// <summary>
        /// 病证
        /// </summary>
        public DbSet<Disease> Diseases { get; set; }
        /// <summary>
        /// 草药
        /// </summary>
        public DbSet<Herb> Herbs { get; set; }

        /// <summary>
        /// 舌形
        /// </summary>
        public DbSet<TongueShape> TongueShapes { get; set; }

        /// <summary>
        /// 舌色
        /// </summary>
        public DbSet<TongueColor> TongueColors { get; set; }

        /// <summary>
        /// 舌态
        /// </summary>
        public DbSet<TongueStatus> TongueStatus { get; set; }

        /// <summary>
        /// 苔质
        /// </summary>
        public DbSet<TongueFurCharacter> TongueFurCharacters { get; set; }

        /// <summary>
        /// 苔色
        /// </summary>
        public DbSet<TongueFurColor> TongueFurColors { get; set; }

        /// <summary>
        /// 浮脉类
        /// </summary>
        public DbSet<PulseFloat> PulseFloats { get; set; }

        /// <summary>
        /// 沉脉类
        /// </summary>
        public DbSet<PulseDeep> PulseDeeps { get; set; }

        /// <summary>
        /// 迟脉类
        /// </summary>
        public DbSet<PulseSlow> PulseSlows { get; set; }

        /// <summary>
        /// 数脉类
        /// </summary>
        public DbSet<PulseRapid> PulseRapids { get; set; }

        /// <summary>
        /// 虚脉类
        /// </summary>
        public DbSet<PulseFeeble> PulseFeebles { get; set; }

        /// <summary>
        /// 实脉类
        /// </summary>
        public DbSet<PulseExcess> PulseExcesses { get; set; }

        #endregion 实体集合
    }
}
